package com.njuse.jvmfinal.Instruction;

import java.nio.ByteBuffer;

import com.njuse.jvmfinal.Starter;
import com.njuse.jvmfinal.memory.jclass.AccessFlags;
import com.njuse.jvmfinal.memory.jclass.JClass;
import com.njuse.jvmfinal.memory.jclass.Method;
import com.njuse.jvmfinal.memory.jclass.runtimeConstantPool.constant.Constant;
import com.njuse.jvmfinal.memory.jclass.runtimeConstantPool.constant.ref.MethodRef;
import com.njuse.jvmfinal.runtimestructure.Jframe;

public class INVOKE_STATIC extends Instruction {
	public int index;
	@Override
	public  void execute(Jframe frame) {
        JClass clazz = frame.getMymethod().getClazz();
        Constant methodRef = clazz.getRuntimeConstantPool().getConstant(this.index);
        Method method = ((MethodRef) methodRef).findmethod();
        if ((method.accessFlags & AccessFlags.ACC_NATIVE)!=0) return;
        JClass target=method.getClazz();
        
        if (target.isInitok()==false) {
        	frame.setPc(frame.getPc()-3);
        	target.init(frame.getMythread());
        	return;
        }
        Jframe newframe=new Jframe(frame.getMythread(),method,method.getMaxStack(),method.getMaxLocal());
        int argc = method.getArgc(); 
        Object[] argv = new Object[argc];
        for (int i = 0; i < argc; i++) {
        	int top=frame.getStacktop();
        	top--;
            argv[i] = frame.getManagestack()[top];
            frame.setStacktop(top);
        }   
        Object[] localvars=new Object[method.getMaxLocal()];
        for (int i = 0; i <argc; i++) {
            localvars[i]=argv[argc - i-1];
        }
        newframe.setLocal(localvars);
        
        if (method.getName().equals("equalInt")) {
          	int top=frame.getStacktop();
          	int a=(int)newframe.getLocal()[0];
          	int b=(int)newframe.getLocal()[1];
          	if (a==b) {
          		frame.getManagestack()[top]=(Object) 1;
          		frame.setStacktop(top+1);
          	}
          	if (a!=b) throw new RuntimeException(a+"!="+b);
          	return;	
        }
        if (method.getName().equals("equalFloat")) {
          	int top=frame.getStacktop();
          	int a=(int)newframe.getLocal()[0];
          	int b=(int)newframe.getLocal()[1];
          	float aa=Float.intBitsToFloat(a);
          	float bb=Float.intBitsToFloat(b);
          	if (aa==bb) {
          		frame.getManagestack()[top]=(Object) 1;
          		frame.setStacktop(top+1);
          	}
          	if (aa!=bb) throw new RuntimeException(aa+"!="+bb);
          	return;	
        }
        if (method.getName().equals("reach")) {
        	int a=(int)newframe.getLocal()[0];
        	System.err.println(a);
        //	Starter.ins=Starter.ins+a+" ";
        	System.out.println(a);
        	return;
        }
        frame.getMythread().push(newframe);    
	}
	
	@Override
	public void readindex(ByteBuffer reader) {
		this.index=(int)reader.getShort();
	}
	

}
